#include "../common.hpp"
#include <map>

#include "vertexbuffer.hpp"

namespace mix
{


VertexBuffer::VertexBuffer()
	: _vbObjs[0](0), _vbObjs[1](0)
{
}

VertexBuffer::~VertexBuffer() {
	deleteRes();
}

void VertexBuffer::deleteRes() {
	if ( _vbObjs[0]) {
		if ( _vbObjs[1]) {
			glDeleteBuffers( 2, _vbObjs);
			_vbObjs[0] = 0;
			_vbObjs[1] = 0;
		} else {
			glDeleteBuffers( 1, _vbObjs);
			_vbObjs[0] = 0;
		}
	} else if ( _vbObjs[1]) {
		glDeleteBuffers( 1, _vbObjs + 1);
		_vbObjs[1] = 0;
	}
}

void VertexBuffer::bind() {
	if ( _vbObjs[0])
		glBindBuffer( GL_ARRAY_BUFFER, _vbObjs[0]);
	if ( _vbObjs[1])
		glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, _vbObjs[1]);
}

int VertexBuffer::setData( const void* vData, int vNum, int vStride, const GLushort* iData/* = NULL*/, int iNum/* = 0*/) {
	if ( _vbObjs[0] || _vbObjs[1])
		return MGE_ResExisted;
	if ( iData)
		glGenBuffers( 2, _vbObjs);
	else
		glGenBuffers( 1, _vbObjs);
	glBindBuffer( GL_ARRAY_BUFFER, _vbObjs[0]);
	glBufferData( GL_ARRAY_BUFFER, vStride * vNum, vData, GL_STATIC_DRAW);
	if ( _vbObjs[1] ) {
		glBindBuffer( GL_ARRAY_BUFFER, _vbObjs[1]);
		glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * iNum,
					  iData, GL_STATIC_DRAW);
	}
}

int VertexBuffer::setData( const GLushort* iData, int iNum) {
}


typedef std::map<std::string, VertexBuffer::Ptr> VB_MAP;
static VB_MAP _vbMap;

void VertexBuffer::onWeakPtrRelease( VertexBuffer::Ptr& ptr) {
	int count = ptr.use_count();
	if ( ptr.use_count() <= 2) {
		_vbMap.erase( ptr->_identName);
		ptr.reset();
	}
}

VertexBuffer::WeakPtr VertexBuffer::require( const char* identName) {
	auto it = _vbMap.find( identName);
	if ( it != _vbMap.end()) {
		return VertexBuffer::WeakPtr( it->second, onWeakPtrRelease);
	}

	VertexBuffer::Ptr ptr( new VertexBuffer());
	ptr->_identName = identName;
	_vbMap[identName] = ptr;
	return VertexBuffer::WeakPtr( ptr, onWeakPtrRelease);
}



}	// namespace mix